import { LibraryLoader } from "./LibraryLoader";
import { ThrowError } from "../../gengine/debug/ThrowError";
import { LibraryEvent } from "../events/LibraryEvent";
import { Log } from "../../gengine/debug/Log";
import { Global } from "../../gengine/global/Global";
import ByteArray = require("bytearray-node")
//class Library
    
    export  class Library /* flash.events.EventDispatcher */
    {
        constructor(arg1: string)
        {
            
            this._LoaderContext = new Object /* flash.system.LoaderContext */();
            this._dicUrlName = new Map<any, any> /* flash.utils.Dictionary */();
            this._this = this;
            this._name = arg1;
            this.initialize();
            this._loaderContext = new Object /* flash.system.LoaderContext */(false, new Object /* flash.system.ApplicationDomain */(null));
            return;
        }

        public embedSWFS(arg1: Array<any>): void
        {
            var loc1=null;
            var loc2=null;
            if (this._enterFrameDispatcher.hasEventListener(flash.events.Event.ENTER_FRAME)) 
            {
                this._enterFrameDispatcher.removeEventListener(flash.events.Event.ENTER_FRAME, this.onEnterFrame);
            }
            this._embeddedComplete = false;
            var loc3=arg1.length;
            var loc4=0;
            while (loc4 < loc3) 
            {
                loc2 = Class(arg1[loc4]);
                loc1 = new LibraryLoader();
                loc1.loadBytes(new loc2() as ByteArray, this._loaderContext);
                this._embeddedLoaders.push(loc1);
                ++loc4;
            }
            this._enterFrameDispatcher.addEventListener(flash.events.Event.ENTER_FRAME, this.onEnterFrame, false, 0, true);
            return;
        }

        public hasDefinition(arg1: string): Boolean
        {
            return this._loaderContext.applicationDomain.hasDefinition(arg1);
        }

        public getDefinition(arg1: string): Class
        {
            var loc1=this._loaderContext.applicationDomain.getDefinition(arg1) as Class;
            if (loc1) 
            {
                return loc1;
            }
            ThrowError.show("ReferenceError: Error #1065: Variable " + arg1 + " is not defined.");
            return null;
        }

        public contains(arg1: string): Boolean
        {
            var loc1=null;
            var loc2=this._embeddedLoaders.length;
            var loc3=0;
            while (loc3 < loc2) 
            {
                loc1 = LibraryLoader(this._embeddedLoaders[loc3]);
                if (loc1.contentLoaderInfo.applicationDomain.hasDefinition(arg1)) 
                {
                    return true;
                }
                ++loc3;
            }
            return false;
        }

        public reset(): void
        {
            this.destroy();
            this.initialize();
            return;
        }

        public destroy(): void
        {
            var loc1=null;
            var loc2=0;
            var loc3=0;
            if (this._enterFrameDispatcher.hasEventListener(flash.events.Event.ENTER_FRAME)) 
            {
                this._enterFrameDispatcher.removeEventListener(flash.events.Event.ENTER_FRAME, this.onEnterFrame);
            }
            loc2 = this._runtimeLoaders.length;
            loc3 = 0;
            while (loc3 < loc2) 
            {
                loc1 = LibraryLoader(this._runtimeLoaders[loc3]);
                if (this._runtimeCompletes[loc3]) 
                {
                    loc1.unload();
                }
                else 
                {
                    loc1.contentLoaderInfo.removeEventListener(flash.events.ProgressEvent.PROGRESS, this.onLoaderProgress);
                    loc1.close();
                }
                ++loc3;
            }
            loc2 = this._embeddedLoaders.length;
            loc3 = 0;
            while (loc3 < loc2) 
            {
                loc1 = LibraryLoader(this._embeddedLoaders[loc3]);
                loc1.unload();
                ++loc3;
            }
            this._embeddedLoaders = null;
            this._runtimeLoaders = null;
            this._runtimeCompletes = null;
            this._enterFrameDispatcher = null;
            this._name = null;
            this._bytesLoaded = undefined;
            this._bytesTotal = undefined;
            return;
        }

        /* internal  */initialize(): void
        {
            this._embeddedLoaders = new Array<any>();
            this._runtimeLoaders = new Array<any>();
            this._runtimeCompletes = new Array<any>();
            this._enterFrameDispatcher = new Object /* flash.display.Sprite */();
            this._bytesLoaded = 0;
            this._bytesTotal = 0;
            return;
        }

        /* internal  */onEnterFrame(arg1: Object /* flash.events.Event */): void
        {
            this._enterFrameDispatcher.removeEventListener(flash.events.Event.ENTER_FRAME, this.onEnterFrame);
            this._embeddedComplete = true;
            dispatchEvent(new LibraryEvent(LibraryEvent.EMBED_COMPLETE, null, false, false));
            return;
        }

        /* internal  */onLoaderProgress(arg1: Object /* flash.events.ProgressEvent */): void
        {
            this.checkLoadersProgress();
            return;
        }

        /* internal  */onLoaderComplete(arg1: Object /* flash.events.Event */): void
        {
            var loc1=LibraryLoader(arg1.target.loader);
            this.removeLoaderEvent(loc1);
            var loc2=this._dicUrlName[loc1.getUrl()];
            dispatchEvent(new LibraryEvent(LibraryEvent.SINGLELOAD_COMPLETE, loc2, false, false));
            var loc3=this._runtimeLoaders.length;
            var loc4=0;
            while (loc4 < loc3) 
            {
                if (loc1 == LibraryLoader(this._runtimeLoaders[loc4])) 
                {
                    this._runtimeCompletes[loc4] = true;
                    break;
                }
                ++loc4;
            }
            this.checkLoadersProgress(true);
            return;
        }

        /* internal  */onIOErrorHandler(arg1: Object /* flash.events.ErrorEvent */): void
        {
            Log.system("library:" + arg1.text);
            if (Global.isDebugModle) 
            {
                dispatchEvent(new Object /* flash.events.ErrorEvent */(flash.events.ErrorEvent.ERROR, false, false, arg1.text));
            }
            if (typeof arg1.target.loader === "libraryloader") 
            {
                this.removeLoaderEvent(arg1.target.loader as LibraryLoader);
            }
            return;
        }

        /* internal  */removeLoaderEvent(arg1: LibraryLoader): void
        {
            arg1.contentLoaderInfo.removeEventListener(flash.events.ProgressEvent.PROGRESS, this.onLoaderProgress, false);
            arg1.contentLoaderInfo.removeEventListener(flash.events.Event.COMPLETE, this.onLoaderComplete, false);
            arg1.contentLoaderInfo.removeEventListener(flash.events.IOErrorEvent.IO_ERROR, this.onIOErrorHandler, false);
            arg1.contentLoaderInfo.removeEventListener(flash.events.SecurityErrorEvent.SECURITY_ERROR, this.onIOErrorHandler, false);
            return;
        }

        /* internal  */checkLoadersProgress(arg1: Boolean=false): void
        {
            var loc3=null;
            var loc1=0;
            var loc2=0;
            arg1 = true;
            var loc4=this._runtimeLoaders.length;
            var loc5=0;
            while (loc5 < loc4) 
            {
                loc3 = LibraryLoader(this._runtimeLoaders[loc5]);
                loc1 = loc1 + loc3.contentLoaderInfo.bytesTotal;
                loc2 = loc2 + loc3.contentLoaderInfo.bytesLoaded;
                if (!this._runtimeCompletes[loc5]) 
                {
                    arg1 = false;
                }
                ++loc5;
            }
            this._bytesLoaded = loc2;
            this._bytesTotal = loc1;
            if (arg1) 
            {
                this._runtimeComplete = true;
                dispatchEvent(new LibraryEvent(LibraryEvent.LOAD_COMPLETE, null, false, false));
            }
            else 
            {
                dispatchEvent(new Object /* flash.events.ProgressEvent */(flash.events.ProgressEvent.PROGRESS, false, false, loc2, loc1));
            }
            return;
        }

        public get name(): string
        {
            return this._name;
        }

        public get bytesLoaded(): number
        {
            return this._bytesLoaded;
        }

        public get bytesTotal(): number
        {
            return this._bytesTotal;
        }

        public get complete(): Boolean
        {
            return this._embeddedComplete && this._runtimeComplete;
        }

        public get embeddedComplete(): Boolean
        {
            return this._embeddedComplete;
        }

        public get runtimeComplete(): Boolean
        {
            return this._runtimeComplete;
        }

        public loadSWF(arg1: string, arg2: string=""): void
        {
            var loc1=new LibraryLoader();
            this._dicUrlName[arg1] = arg2;
            loc1.contentLoaderInfo.addEventListener(flash.events.ProgressEvent.PROGRESS, this.onLoaderProgress, false, 0, true);
            loc1.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, this.onLoaderComplete, false, 0, true);
            loc1.contentLoaderInfo.addEventListener(flash.events.IOErrorEvent.IO_ERROR, this.onIOErrorHandler, false, 0, true);
            loc1.contentLoaderInfo.addEventListener(flash.events.SecurityErrorEvent.SECURITY_ERROR, this.onIOErrorHandler, false, 0, true);
            loc1.load(new Object /* flash.net.URLRequest */(arg1), this._loaderContext);
            this._runtimeLoaders.push(loc1);
            this._runtimeCompletes.push(false);
            return;
        }

        public embedSWF(arg1: Class): void
        {
            var loc1=new LibraryLoader();
            loc1.loadBytes(new arg1() as ByteArray, this._loaderContext);
            this._embeddedLoaders.push(loc1);
            return;
        }

        public loadSWFS(arg1: Array<any>): void
        {
            this._runtimeComplete = false;
            var loc1=arg1.length;
            var loc2=0;
            while (loc2 < loc1) 
            {
                this.loadSWF(arg1[loc2] as string);
                ++loc2;
            }
            return;
        }

        private /* var */_loaderContext: Object /* flash.system.LoaderContext */;

        private /* var */_enterFrameDispatcher: Object /* flash.display.Sprite */;

        private /* var */_embeddedLoaders: Array<any>;

        private /* var */_runtimeLoaders: Array<any>;

        private /* var */_embeddedComplete: Boolean;

        private /* var */_runtimeCompletes: Array<any>;

        private /* var */_runtimeComplete: Boolean;

        private /* var */_name: string;

        private /* var */_bytesLoaded: number=0;

        private /* var */_bytesTotal: number=0;

        private /* var */_LoaderContext: Object /* flash.system.LoaderContext */;

        private /* var */_dicUrlName: Map<any, any> /* flash.utils.Dictionary */;

        private /* var */_this: Library;
    }
